﻿namespace Blaze.Framework.Loaders
{
    using System;
    using System.Collections.Generic;
    using UnityEngine;

    /// <summary>
    /// 跟踪资源加载器的引用状况。
    /// </summary>
    public class AssetLoaderTracer : MonoBehaviour
    {
        public int RefCount;
        public WeakReference Reference;
        public string Uri;

        /// <summary>
        /// 获取正在跟踪的加载器类型。
        /// </summary>
        public Type TracingType { get; private set; }

        private static Transform Root
        {
            get
            {
                if (mRoot == null)
                {
                    mRoot = new GameObject("AssetLoaders").transform;
                    mRoot.SetParent(Singleton.Root.transform);
                }
                return mRoot;
            }
        }

        /// <summary>
        /// 跟踪指定的<see cref="IAssetLoader"/>状态。
        /// </summary>
        /// <param name="loader"></param>
        public static void Trace(AssetLoaderBase loader)
        {
            var loaderType = loader.GetType();
            var tracerObj = new GameObject(loader.Uri);
            var tracer = tracerObj.AddComponent<AssetLoaderTracer>();
            tracer.mLoaderType = loaderType;
            var root = getRootByLoaderType(loaderType);
            tracerObj.transform.SetParent(root, false);
            root.name = string.Format("{0} ({1})", loaderType.Name, root.childCount);
            tracer.Reference = new WeakReference(loader);
        }

        private static Transform getRootByLoaderType(Type loaderType)
        {
            Transform child;
            if (mLoaderRoots.TryGetValue(loaderType, out child))
                return child;

            child = new GameObject().transform;
            child.SetParent(Root, false);
            mLoaderRoots.Add(loaderType, child);
            return child;
        }

        private void Update()
        {
            var loader = (AssetLoaderBase) Reference.Target;
            if (loader == null || loader.IsDisposed)
            {
                var root = getRootByLoaderType(mLoaderType);
                root.name = string.Format("{0} ({1})", mLoaderType.Name, root.childCount - 1);
                DestroyImmediate(gameObject, false);
                return;
            }

            RefCount = loader.RefCount;
            Uri = loader.Uri;
        }

        private static Transform mRoot;
        private Type mLoaderType;
        private static readonly Dictionary<Type, Transform> mLoaderRoots = new Dictionary<Type, Transform>();
    }
}